package com.z.system.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.z.system.dto.UserDTO;
import com.z.system.exception.BusinessException;
import com.z.system.model.Role;
import com.z.system.model.User;
import com.z.system.repository.RoleRepository;
import com.z.system.repository.UserRepository;
import com.z.system.service.UserService;

/**
 * 用户服务实现类
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public User getCurrentUser() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal instanceof User) {
            return ((User) principal);
        }
        return null;
    }

    @Override
    public User getUserById(UUID id) {
        return userRepository.findById(id).orElse(null);
    }

    @Override
    public User getUserByUsername(String username) {
        return userRepository.findByUsername(username).orElse(null);
    }

    @Override
    public User getUserByUserSn(String userSn) {
        return userRepository.findByUserSn(userSn).orElse(null);
    }

    @Override
    public Page<UserDTO> getUsers(Pageable pageable, Map<String, Object> params) {
        // 使用原生SQL实现灵活的动态查询
        int page = pageable.getPageNumber();
        int size = pageable.getPageSize();
        int offset = page * size;

        // 构建动态查询条件
        StringBuilder whereClause = new StringBuilder("WHERE u.del = 0");
        List<Object> queryParams = new ArrayList<>();

        // 提取查询条件参数
        String username = params != null && params.containsKey("username") ? (String) params.get("username") : null;
        String userSn = params != null && params.containsKey("userSn") ? (String) params.get("userSn") : null;
        String email = params != null && params.containsKey("email") ? (String) params.get("email") : null;
        UUID deptId = params != null && params.containsKey("deptId") ? (UUID) params.get("deptId") : null;
        Integer enable = params != null && params.containsKey("enable") ? (Integer) params.get("enable") : null;

        // 添加查询条件
        if (username != null && !username.trim().isEmpty()) {
            whereClause.append(" AND u.username LIKE ?");
            queryParams.add("%" + username + "%");
        }
        if (userSn != null && !userSn.trim().isEmpty()) {
            whereClause.append(" AND u.user_sn LIKE ?");
            queryParams.add("%" + userSn + "%");
        }
        if (email != null && !email.trim().isEmpty()) {
            whereClause.append(" AND u.email LIKE ?");
            queryParams.add("%" + email + "%");
        }
        if (deptId != null) {
            whereClause.append(" AND u.dept_id = ?");
            queryParams.add(deptId);
        }
        if (enable != null) {
            whereClause.append(" AND u.enable = ?");
            queryParams.add(enable);
        }

        // 构建SQL查询
        String sql = "SELECT u.id, u.username, u.email, u.phone, u.sex, u.enable, u.user_sn, u.remark, " +
                "u.nickname, u.head_img_url, u.create_time, u.update_time, u.dept_id, d.name as dept_name " +
                "FROM t_user u LEFT JOIN t_dept d ON u.dept_id = d.id " + whereClause.toString() + " " +
                "ORDER BY u.create_time DESC LIMIT ? OFFSET ?";

        String countSql = "SELECT COUNT(*) FROM t_user u LEFT JOIN t_dept d ON u.dept_id = d.id "
                + whereClause.toString();

        // 准备查询参数
        List<Object> dataQueryParams = new ArrayList<>(queryParams);
        dataQueryParams.add(size);
        dataQueryParams.add(offset);

        // 执行数据查询
        List<UserDTO> userDTOs = jdbcTemplate.query(sql, dataQueryParams.toArray(), new RowMapper<UserDTO>() {
            @Override
            public UserDTO mapRow(java.sql.ResultSet rs, int rowNum) throws java.sql.SQLException {
                UserDTO userDTO = new UserDTO();
                // 所有属性都是String类型，需要正确转换
                userDTO.setId(rs.getString("id"));
                userDTO.setUserName(rs.getString("username"));
                userDTO.setUserEmail(rs.getString("email"));
                userDTO.setUserPhone(rs.getString("phone"));
                // 格式化性别：1=男，0=女
                Integer sex = rs.getInt("sex");
                userDTO.setUserGender(sex != null ? (sex == 1 ? "男" : "女") : null);
                // 格式化状态：启用=1，禁用=2
                Integer enable = rs.getInt("enable");
                userDTO.setStatus(enable != null ? (enable == 1 ? "1" : "2") : "2");
                userDTO.setUserSn(rs.getString("user_sn"));
                userDTO.setRemark(rs.getString("remark"));
                userDTO.setNickName(rs.getString("nickname"));
                userDTO.setHeadImgUrl(rs.getString("head_img_url"));
                // 格式化日期
                java.sql.Timestamp createTime = rs.getTimestamp("create_time");
                userDTO.setCreateTime(
                        createTime != null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTime) : null);
                java.sql.Timestamp updateTime = rs.getTimestamp("update_time");
                userDTO.setUpdateTime(
                        updateTime != null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(updateTime) : null);
                userDTO.setDeptId(rs.getString("dept_id"));
                userDTO.setDeptName(rs.getString("dept_name"));
                return userDTO;
            }
        });

        // 执行总数查询
        Long total = jdbcTemplate.queryForObject(countSql, queryParams.toArray(), Long.class);

        // 创建Page对象返回
        return new PageImpl<>(userDTOs, pageable, total != null ? total : 0);
    }

    @Override
    public List<User> getUsers(Map<String, Object> params) {
        // 这里可以根据参数构建查询条件
        // 简化实现，直接返回所有用户
        return userRepository.findAll();
    }

    @Override
    public User saveUser(User user) {
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(user.getUsername())) {
            throw new BusinessException("用户名已存在");
        }
        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(user.getEmail())) {
            throw new BusinessException("邮箱已存在");
        }
        // 检查工号是否已存在
        if (StringUtils.hasText(user.getUserSn()) && userRepository.existsByUserSn(user.getUserSn())) {
            throw new BusinessException("工号已存在");
        }
        // 加密密码
        if (StringUtils.hasText(user.getPassword())) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        } else {
            user.setPassword(passwordEncoder.encode("1111"));
        }
        // 设置创建时间
        if (user.getCreateTime() == null) {
            user.setCreateTime(new Date());
        }
        return userRepository.save(user);
    }

    @Override
    public User updateUser(User user) {
        User existingUser = userRepository.findById(user.getId()).orElseThrow(() -> new BusinessException("用户不存在"));

        // 检查用户名是否已存在（排除当前用户）
        if (!existingUser.getUsername().equals(user.getUsername()) &&
                userRepository.existsByUsername(user.getUsername())) {
            throw new BusinessException("用户名已存在");
        }
        // 检查邮箱是否已存在（排除当前用户）
        if (!existingUser.getEmail().equals(user.getEmail()) &&
                userRepository.existsByEmail(user.getEmail())) {
            throw new BusinessException("邮箱已存在");
        }
        // 检查工号是否已存在（排除当前用户）
        if (StringUtils.hasText(user.getUserSn()) && !Objects.equals(existingUser.getUserSn(), user.getUserSn()) &&
                userRepository.existsByUserSn(user.getUserSn())) {
            throw new BusinessException("工号已存在");
        }

        // 保留原密码（除非明确设置了新密码）
        if (!StringUtils.hasText(user.getPassword())) {
            user.setPassword(existingUser.getPassword());
        } else if (!user.getPassword().equals(existingUser.getPassword())) {
            // 新密码不等于原密码，需要加密
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        }

        // 设置更新时间
        user.setUpdateTime(new Date());

        return userRepository.save(user);
    }

    @Override
    public void deleteUser(UUID id) {
        User user = userRepository.findById(id).orElseThrow(() -> new BusinessException("用户不存在"));
        userRepository.delete(user);
    }

    @Override
    public void deleteUsers(Set<UUID> ids) {
        List<User> users = userRepository.findAllById(ids);
        if (users.size() != ids.size()) {
            throw new BusinessException("部分用户不存在");
        }
        userRepository.deleteAll(users);
    }

    @Override
    public void updateUserStatus(UUID id, Integer enable) {
        User user = userRepository.findById(id).orElseThrow(() -> new BusinessException("用户不存在"));
        user.setEnable(enable);
        user.setUpdateTime(new Date());
        userRepository.save(user);
    }

    @Override
    public void resetPassword(UUID id, String password) {
        User user = userRepository.findById(id).orElseThrow(() -> new BusinessException("用户不存在"));
        user.setPassword(passwordEncoder.encode(password));
        user.setUpdateTime(new Date());
        userRepository.save(user);
    }

    @Override
    public void changePassword(String oldPassword, String newPassword) {
        User currentUser = getCurrentUser();
        if (currentUser == null) {
            throw new BusinessException("用户未登录");
        }
        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, currentUser.getPassword())) {
            throw new BusinessException("旧密码不正确");
        }
        // 设置新密码
        currentUser.setPassword(passwordEncoder.encode(newPassword));
        currentUser.setUpdateTime(new Date());
        userRepository.save(currentUser);
    }

    @Override
    public void assignRoles(UUID userId, Set<UUID> roleIds) {
        // 检查用户是否存在
        userRepository.findById(userId).orElseThrow(() -> new BusinessException("用户不存在"));

        // 检查角色是否存在
        List<UUID> existingRoleIds = roleRepository.findAllById(roleIds).stream()
                .map(Role::getId).collect(Collectors.toList());
        if (existingRoleIds.size() != roleIds.size()) {
            throw new BusinessException("部分角色不存在");
        }

        // 由于我们已经移除了实体关联，实际应用中这里需要使用JdbcTemplate等执行原生SQL来更新用户角色关联表
        // 这里简化处理，保留更新时间
        User user = userRepository.findById(userId).orElseThrow(() -> new BusinessException("用户不存在"));
        user.setUpdateTime(new Date());
        userRepository.save(user);
    }

    @Override
    public Set<UUID> getUserRoleIds(UUID userId) {
        // 检查用户是否存在
        userRepository.findById(userId).orElseThrow(() -> new BusinessException("用户不存在"));

        // 使用原生SQL查询用户角色ID
        return userRepository.findRoleIdsByUserIdNative(userId);
    }
}